﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;
using CMISForSharePoint.cmisHelpers;
using CMISForSharePoint.cmisTypes;
using CMISForSharePoint.cmisEnums;
using CMISForSharePoint.Divers;


namespace CMISForSharePoint.CmisServices.NavigationService
{
    public class NavigationService:INavigationService
    {
        #region INavigationService Members

        public getDescendantsResponse getDescendants(getDescendants param)
        {
            using (SPHelper spHelper = new SPHelper())
            {
                //test
                //param.type = enumTypesOfFileableObjects.any;
                //param.folderId = "855e38f7-a639-45b3-bbea-c8a708915a2d";
                //param.repositoryId = "d63c9765-a108-43df-a3ba-4e355b8c4c5f";
                ////////param.orderByClause = "Name ASC";
                //param.filter = "Name,URI,ObjectId";
                ////////param.depth = "1";
                /////////////////////////////////

                getDescendantsResponse response = new getDescendantsResponse();
                response.@object = new cmisObjectType[1];
                SPFolder folder;

                SPDocumentLibrary myDocLib = spHelper.GetDocumentLibrary(new Guid(param.repositoryId));
                if (param.folderId != myDocLib.RootFolder.UniqueId.ToString())
                {
                    SPListItem item = myDocLib.GetItemByUniqueId(new Guid(param.folderId));
                    folder = item.Folder;
                }
                else
                {
                    folder = myDocLib.RootFolder;
                }


                cmisObjectType obj = new cmisObjectType();
                int depth = 1;

                if (int.TryParse(param.depth, out depth))
                {
                    if (depth < 0)
                    {
                        depth = 10;
                    }
                }
                else
                {
                    depth = 1;
                }

                if (String.IsNullOrEmpty(param.filter))
                {
                    param.filter = "*";
                }
                string[] filter = CmisHelper.CmisFilterParser(param.filter);

                bool includeAllowableActions = false;
                if (param.includeAllowableActions.HasValue)
                {
                    includeAllowableActions = param.includeAllowableActions.Value;
                }

                enumRelationshipDirection includeRelationships = enumRelationshipDirection.none;
                if (param.includeRelationships.HasValue)
                {
                    includeRelationships = param.includeRelationships.Value;
                }


                obj = spHelper.SPfolderTreeToCmisObjectType(obj, folder, depth, filter,
                                                            param.type, includeAllowableActions
                                                            , includeRelationships, param.orderByClause
                                                            );

                response.@object = obj.child;
                return response;

            }
        }

        public getChildrenResponse getChildren(getChildren param)
        {
            //test
            //param.type = enumTypesOfFileableObjects.documents;
            //param.folderId = "855e38f7-a639-45b3-bbea-c8a708915a2d";
            //param.repositoryId = "d63c9765-a108-43df-a3ba-4e355b8c4c5f";
            //param.orderByClause = "Name ASC";
            //param.filter = "Name,URI";

            /////////////////////////
            getChildrenResponse response = new getChildrenResponse();
            getDescendants descendantParam = new getDescendants();

            descendantParam.depth = "1";
            descendantParam.filter = param.filter;
            descendantParam.folderId = param.folderId;
            descendantParam.includeAllowableActions = param.includeAllowableActions;
            descendantParam.includeAllowableActionsSpecified = param.includeAllowableActionsSpecified;
            descendantParam.includeRelationships = param.includeRelationships;
            descendantParam.includeRelationshipsSpecified = param.includeRelationshipsSpecified;
            descendantParam.repositoryId = param.repositoryId;
            descendantParam.type = param.type;
            descendantParam.typeSpecified = param.typeSpecified;
            descendantParam.orderByClause = param.orderByClause;


            getDescendantsResponse descendantresponse = getDescendants(descendantParam);

            response.@object = descendantresponse.@object;

            int maxItems = 0;
            int skipCount = 0;
            if (int.TryParse(param.skipCount, out skipCount) && skipCount > 0 && skipCount < response.@object.Count())
            {
                response.@object = response.@object.Skip(skipCount).ToArray();
            }

            response.hasMoreItems = false;
            if (int.TryParse(param.maxItems, out maxItems) && maxItems < response.@object.Count())
            {
                response.@object = response.@object.Take(maxItems).ToArray();
                response.hasMoreItems = true;

            }






            return response;
        }

        public getFolderParentResponse getFolderParent(getFolderParent param)
        {
            //test
            //param.folderId = "b07d1bf1-83e3-473a-a2c6-9ed588e5f419";
            //  /*Root folder id*/ "855e38f7-a639-45b3-bbea-c8a708915a2d"
            //
            //param.repositoryId = "d63c9765-a108-43df-a3ba-4e355b8c4c5f";
            //param.returnToRoot = true;
            //param.returnToRootSpecified = true;
            //param.filter = "Name";
            ///////////////////////
            using (SPHelper spHelper = new SPHelper())
            {

                getFolderParentResponse response = new getFolderParentResponse();
                SPFolder folder;
                List<cmisObjectType> path = new List<cmisObjectType>();

                SPDocumentLibrary myDocLib = spHelper.GetDocumentLibrary(new Guid(param.repositoryId));

                bool isRootFolder = (param.folderId == myDocLib.RootFolder.UniqueId.ToString());
                bool includeAllowableActions = param.includeAllowableActionsSpecified && param.includeAllowableActions.HasValue && param.includeAllowableActions.Value && !isRootFolder;
                bool includeRelationships = param.includeRelationshipsSpecified && param.includeRelationships.HasValue && param.includeRelationships.Value != enumRelationshipDirection.none;
                bool returnToRoot = param.returnToRootSpecified && param.returnToRoot.HasValue && param.returnToRoot.Value;


                //Managing the repository's rootFolder 
                if (!isRootFolder)
                {
                    SPListItem item = myDocLib.GetItemByUniqueId(new Guid(param.folderId));

                    /*the function returns only the parentFolder  if returnToRoot==true else it returns all the path starting from the parameter's specified folder*/
                    if (returnToRoot)
                    {
                        folder = item.Folder;
                    }
                    else
                    {
                        folder = item.Folder.ParentFolder;
                    }


                }
                else
                {
                    folder = myDocLib.RootFolder;
                }

                //Managing the filter
                if (String.IsNullOrEmpty(param.filter))
                {
                    param.filter = "*";
                }
                else if (param.filter != "*")
                {
                    param.filter += ",ParentId";
                }
                string[] filter = CmisHelper.CmisFilterParser(param.filter);

                //getting the first parent
                cmisObjectType obj = spHelper.cmisFolderFactory(folder);
                //filtring properties
                obj.properties.Items = CmisHelper.CmisPropertyFilter(obj.properties.Items, filter);


                //setting the first parent allowable actions
                if (includeAllowableActions)
                {
                    obj.allowableActions = spHelper.cmisAllowableActionsFactory(folder.Item);
                }

                #region not suported :Relationship
                /*the relationship paradigim is not available in sharepoint*/
                //if ()
                //{
                //    obj.relationship =new cmisObjectType[]{ spHelper.cmisRelationshipFactory(folder.Item, param.includeRelationships.Value)};
                //}
                #endregion
                //ading the object to the path
                path.Add(obj);

                //Getting the path to the root folder
                if (returnToRoot)
                {

                    while (folder.UniqueId.ToString() != myDocLib.RootFolder.UniqueId.ToString())
                    {
                        folder = folder.ParentFolder;
                        obj = spHelper.cmisFolderFactory(folder);
                        //filtring properties
                        obj.properties.Items = CmisHelper.CmisPropertyFilter(obj.properties.Items, filter);
                        //setting the allowable actions
                        if (param.includeAllowableActionsSpecified && param.includeAllowableActions.HasValue && param.includeAllowableActions.Value && !isRootFolder)
                        {
                            obj.allowableActions = spHelper.cmisAllowableActionsFactory(folder.Item);
                        }

                        path.Add(obj);
                    }

                }

                response.@object = path.ToArray();

                return response;

            }
        }

        public getObjectParentsResponse getObjectParents(getObjectParents param)
        {


            //test
            //param.objectId = "ab9eb43a-9103-46b6-acb2-3bd4d92cc66d";
            ////  
            ////
            //param.repositoryId = "d63c9765-a108-43df-a3ba-4e355b8c4c5f";
            ////
            //param.filter = "Name";
            /////////////////////
            using (SPHelper spHelper = new SPHelper())
            {

                getObjectParentsResponse response = new getObjectParentsResponse();

                List<cmisObjectType> path = new List<cmisObjectType>();

                SPDocumentLibrary myDocLib = spHelper.GetDocumentLibrary(new Guid(param.repositoryId));
                SPListItem item = myDocLib.GetItemByUniqueId(new Guid(param.objectId));
                SPFile file;
                bool includeAllowableActions = param.includeAllowableActionsSpecified && param.includeAllowableActions.HasValue && param.includeAllowableActions.Value;
                bool includeRelationships = param.includeRelationshipsSpecified && param.includeRelationships.HasValue && param.includeRelationships.Value != enumRelationshipDirection.none;

                if (item != null && item.File != null && item.File.ParentFolder != null)
                {
                    file = item.File;
                }
                else
                {
                    return response;
                }

                //managing the filter parameter
                if (String.IsNullOrEmpty(param.filter))
                {
                    param.filter = "*";
                }
                string[] filter = CmisHelper.CmisFilterParser(param.filter);

                //creating the object and applying the filter
                cmisObjectType obj = spHelper.cmisFolderFactory(file.ParentFolder);
                obj.properties.Items = CmisHelper.CmisPropertyFilter(obj.properties.Items, filter);


                //setting the parent allowable actions
                if (includeAllowableActions)
                {
                    obj.allowableActions = spHelper.cmisAllowableActionsFactory(file.ParentFolder.Item);
                }


                #region not suported :Relationship
                /*the relationship paradigim is not available in sharepoint*/
                //if ()
                //{
                //    obj.relationship =new cmisObjectType[]{ spHelper.cmisRelationshipFactory(file.ParentFolder.Item, param.includeRelationships.Value)};
                //}
                #endregion


                path.Add(obj);
                response.@object = path.ToArray();
                return response;

            }
        }

        public getCheckedoutDocsResponse getCheckedoutDocuments(getCheckedoutDocs param)
        {
            //TEST
            //param.folderID=  "855e38f7-a639-45b3-bbea-c8a708915a2d";
            ////  /*folder id*/"e2cbf358-bb0b-431b-a789-f34603153200"
            ////
            // param.repositoryId = "d63c9765-a108-43df-a3ba-4e355b8c4c5f";
            ////////////////////////////////////////////////////////////////////////


            using (SPHelper spHelper = new SPHelper())
            {
                getCheckedoutDocsResponse response = new getCheckedoutDocsResponse();
                List<cmisObjectType> path = new List<cmisObjectType>();

                cmisObjectType obj;
                SPFile file;
                SPDocumentLibrary myDocLib = spHelper.GetDocumentLibrary(new Guid(param.repositoryId));


                int maxItems = 0;
                int skipCount = 0;
                bool includeAllowableActions = param.includeAllowableActionsSpecified && param.includeAllowableActions.HasValue && param.includeAllowableActions.Value;
                bool includeRelationships = param.includeRelationshipsSpecified && param.includeRelationships.HasValue && param.includeRelationships.Value != enumRelationshipDirection.none;

                //managing the filter parameter
                if (String.IsNullOrEmpty(param.filter))
                {
                    param.filter = "*";
                }
                string[] filter = CmisHelper.CmisFilterParser(param.filter);



                foreach (SPListItem item in myDocLib.Items)
                {
                    file = item.File;
                    if (file != null)
                    {

                        if (file.Level == SPFileLevel.Checkout)
                        {
                            //dealing with the folderId parameter
                            if (string.IsNullOrEmpty(param.folderID) || (param.folderID == file.ParentFolder.UniqueId.ToString()))
                            {
                                //creating the object and applying the filter
                                obj = spHelper.cmisDocumentFactory(file);
                                obj.properties.Items = CmisHelper.CmisPropertyFilter(obj.properties.Items, filter);

                                //setting allowable actions
                                if (includeAllowableActions)
                                {
                                    obj.allowableActions = spHelper.cmisAllowableActionsFactory(file.Item);
                                }


                                #region not suported :Relationship
                                /*the relationship paradigim is not available in sharepoint*/
                                //if ()
                                //{
                                //    obj.relationship =new cmisObjectType[]{ spHelper.cmisRelationshipFactory(file.Item, param.includeRelationships.Value)};
                                //}
                                #endregion



                                path.Add(obj);



                            }


                        }

                    }
                }

                //if skipCount is specified 
                if (int.TryParse(param.skipCount, out skipCount) && skipCount > 0 && skipCount < response.@object.Count())
                {
                    response.@object = response.@object.Skip(skipCount).ToArray();
                }


                response.hasMoreItems = false;
                //if maxItems is specified
                if (int.TryParse(param.maxItems, out maxItems) && maxItems < response.@object.Count())
                {
                    response.@object = response.@object.Take(maxItems).ToArray();
                    response.hasMoreItems = true;

                }


                response.@object = path.ToArray();
                return response;

            }
        }
        #endregion



    }
}
